import TaskController from "@/contrib/task/controller"
import { ITransportTask, TaskType } from "@/contrib/task/types"
import { bodyConfigs, createBodyGetter, } from "@/role/bodyUtils"
import { CreepConfig, CreepRole, RoleDatas } from "@/role/types/role"

/**
 * manager 触发后事处理的最小生命
 */
const TRANSFER_DEATH_LIMIT = 120

/**
 * 搬运工，运营单位
 * 负责填充 extension、spawn、tower、lab 等资源运输任务
 */
export const taskManager: CreepConfig<CreepRole.TaskManager> = {
    // isNeed: (room, preMemory, creepName) => {
    //     // // 如果自己被炒鱿鱼了就不再孵化
    //     // if (room.transport.haveCreepBeenFired(creepName)) {
    //     //     room.transport.removeCreep(creepName)
    //     //     return false
    //     // }
    //     // 普通体型的话就一直孵化，特殊体型的话如果还有要做的任务就继续孵化
    //     return !preMemory.bodyType || !!preMemory.taskKey
    // },
    prepare: creep => {
        creep.memory.bodyType = creep.memory.data.bodyType
        return true
    },
    source: creep => {

        const memoryData: RoleDatas[CreepRole.TaskManager] = creep.memory.data as RoleDatas[CreepRole.TaskManager]

        if (creep.ticksToLive <= TRANSFER_DEATH_LIMIT) {

            if (creep.memory.transportTaskId) {
                const transportTask = TaskController.getTransportTaskById(creep.memory.transportTaskId)
                if (transportTask) {
                    TaskController.abandonTask(transportTask.type, transportTask.id)
                }
            }
            return deathPrepare(creep, memoryData.sourceId)
        }

        if (!creep.memory.transportTaskId) {
            if (creep.store.getUsedCapacity() > 0) {
                for (const resourceType in creep.store) {
                    const target = creep.room.storage
                    if (!target) return false
                    // 转移资源
                    creep.goTo(target.pos)
                    creep.transfer(target, <ResourceConstant>resourceType)
                }
                return false
            }
        }

        if (!creep.memory.transportTaskId) {
            const transportTask = TaskController.getTransportTask(creep.room.name) as ITransportTask
            if (transportTask) {
                //
                // fromId, fromRoomName
                TaskController.acceptTask(transportTask.type, transportTask.id)
                creep.memory.transportTaskId = transportTask.id
                creep.memory.targetId = transportTask.fromId as Id<Source | StructureWithStore | ConstructionSite | Resource>
                memoryData.workRoom = transportTask.fromRoomName
            }
        }

        if (creep.memory.transportTaskId) {
            const transportTask = TaskController.getTransportTaskById(creep.memory.transportTaskId)
            if (!transportTask) {
                delete creep.memory.transportTaskId
                return true
            }

            if (creep.store.getFreeCapacity(transportTask.resType) == 0) {
                return true
            }

            if (creep.store[transportTask.resType] == transportTask.amount && creep.store[transportTask.resType] > 0) {
                return true
            }

            if (creep.memory.targetId) {
                //
                // move to workRoom
                if (creep.room.name != memoryData.workRoom) {
                    creep.goTo(new RoomPosition(25, 25, memoryData.workRoom))
                    return
                }

                const target = Game.getObjectById(creep.memory.targetId) as StructureWithStore
                if (target && target['store']) {
                    //
                    // target full, finish task
                    if (target.store[transportTask.resType] == 0) {
                        delete creep.memory.targetId
                        delete memoryData.workRoom
                        TaskController.finishTask(TaskType.TRANSPORT, transportTask.id)
                        return true
                    }
                    //
                    // withdraw
                    let status
                    creep.goTo(target.pos)
                    if (transportTask.amount == 0 || creep.store.getFreeCapacity(transportTask.resType) < transportTask.amount) {
                        status = creep.withdraw(target, transportTask.resType)
                    }
                    else {
                        status = creep.withdraw(target, transportTask.resType, transportTask.amount)
                    }
                    if (status == ERR_NOT_IN_RANGE) {
                        return
                    }
                    else if (status == OK) {
                        delete creep.memory.targetId
                        delete memoryData.workRoom
                        return true
                    }
                }
                else if (target && target['amount']) {
                    const target = Game.getObjectById(creep.memory.targetId) as Resource
                    let status
                    creep.goTo(target.pos)
                    status = creep.pickup(target)
                    if (status == ERR_NOT_IN_RANGE) {
                        return
                    }
                    else if (status == OK) {
                        delete creep.memory.targetId
                        delete memoryData.workRoom
                        return true
                    }
                }
                else {
                    delete creep.memory.targetId
                    delete memoryData.workRoom
                    TaskController.finishTask(TaskType.TRANSPORT, transportTask.id)
                }
            }
        }

        // return Game.rooms[workRoom]?.transport.getWork(creep).source()
        return true
    },
    target: creep => {

        const memoryData: RoleDatas[CreepRole.TaskManager] = creep.memory.data as RoleDatas[CreepRole.TaskManager]

        if (creep.memory.transportTaskId) {
            const transportTask = TaskController.getTransportTaskById(creep.memory.transportTaskId)
            if (!transportTask) {
                delete creep.memory.transportTaskId
                return true
            }

            if (!creep.memory.targetId) {
                //
                // targetId, targetRoom
                creep.memory.targetId = transportTask.targetId as Id<Source | StructureWithStore | ConstructionSite | Resource>
                memoryData.workRoom = transportTask.targetRoomName
            }

            if (creep.memory.targetId) {
                //
                // move to workRoom
                if (creep.room.name != memoryData.workRoom) {
                    creep.goTo(new RoomPosition(25, 25, memoryData.workRoom))
                    return
                }

                const target = Game.getObjectById(creep.memory.targetId) as StructureWithStore
                if (target && target.store.getFreeCapacity(transportTask.resType) > 0) {
                    //
                    // target full, finish task
                    if (target.store.getFreeCapacity(transportTask.resType) == 0) {
                        delete creep.memory.targetId
                        delete memoryData.workRoom
                        TaskController.finishTask(TaskType.TRANSPORT, transportTask.id)
                        return true
                    }
                    //
                    // withdraw
                    creep.goTo(target.pos)
                    const status = creep.transfer(target, transportTask.resType)
                    if (status == ERR_NOT_IN_RANGE) {
                        return false
                    }
                    else if (status == OK) {
                        delete creep.memory.targetId
                        delete memoryData.workRoom
                        TaskController.finishTask(TaskType.TRANSPORT, transportTask.id)
                        return true
                    }
                }
            }

        }

        // return Game.rooms[workRoom]?.transport.getWork(creep).target()
        return true
    },
    bodys: (room, spawn, data) => {
        // // 指定了特殊身体部件的话就生成对应的
        // if (data.bodyType) return specialBodyConfig[data.bodyType](room, spawn)
        // // 否则就使用默认的身体部件
        return createBodyGetter(bodyConfigs.manager)(room, spawn)
        // return calcBodyPart([[CARRY, 4], [MOVE, 2]])
    }
}





// if (!creep.memory.working) {

// }


/**
 * 快死时的后事处理
 * 将资源存放在对应的地方
 * 存完了就自杀
 *
 * @param creep manager
 * @param sourceId 能量存放处
 */
const deathPrepare = function (creep: Creep, sourceId: Id<StructureWithStore>): false {

    if (creep.room.name != creep.memory.spawnRoom) {
        creep.goTo(new RoomPosition(25, 25, creep.memory.spawnRoom))
        return
    }

    if (creep.store.getUsedCapacity() > 0) {
        for (const resourceType in creep.store) {
            let target: StructureWithStore
            // 不是能量就放到 terminal 里
            if (resourceType != RESOURCE_ENERGY && resourceType != RESOURCE_POWER && creep.room.terminal) {
                target = creep.room.terminal
            }
            // 否则就放到 storage 或者玩家指定的地方
            else target = sourceId ? Game.getObjectById(sourceId) : creep.room.storage
            // 刚开新房的时候可能会没有存放的目标
            if (!target) return false

            // 转移资源
            creep.goTo(target.pos)
            creep.transfer(target, <ResourceConstant>resourceType)

            return false
        }
    }
    else creep.suicide()

    return false
}

export default taskManager
